#include <iostream>
using namespace std;

#include"tlistaporo.h"

/***************TListaNodo****************/
//---------------------------------------\\

TListaNodo::TListaNodo()
{
	siguiente = NULL;
	anterior = NULL;
}
TListaNodo::TListaNodo(const TListaNodo& tln)
{
	e = tln.e;
	siguiente = tln.siguiente;
	anterior = tln.anterior;
}
TListaNodo::~TListaNodo()
{
	e.~TPoro();
	if(!siguiente)
	{
		siguiente = NULL;
	}
	if(!anterior)
	{
		anterior = NULL;
	}
}
TListaNodo& TListaNodo::operator=(const TListaNodo& tln)
{
	if((*this) != tln)
	{
		e = tln.e;
		siguiente = tln.siguiente;
		anterior = tln.anterior;
	}
	return *this;
}
bool TListaNodo::operator==(const TListaNodo& tln)
{
	bool iguales = false;
	if( e == tln.e)
	{
		iguales = true;
	}
	return iguales;
}
bool TListaNodo::operator!=(const TListaNodo& tln)
{
	bool distintos = true;
	if( (*this) == tln )
	{
		distintos = false;
	}
	return distintos;
}	


/***************TListaPosicion****************/
//-------------------------------------------\\

TListaPosicion::TListaPosicion()
{
	pos = NULL;
}
TListaPosicion::TListaPosicion(const TListaPosicion& tlp)
{
	pos = tlp.pos;
}
TListaPosicion::~TListaPosicion()
{
	pos = NULL;
}
TListaPosicion& TListaPosicion::operator=(const TListaPosicion& tlp)
{
	pos = tlp.pos;
	
	return(*this);
}
bool TListaPosicion::operator==(const TListaPosicion& tlp)
{
	bool iguales = false;
	if(pos==NULL && tlp.pos==NULL)
	{
		iguales = true;
	}else
	{	
		if(pos == tlp.pos)
		{
			iguales = true;
		}
	}
	return iguales;
}
bool TListaPosicion::operator!=(const TListaPosicion& tlp)
{
	bool distintos = true;
	if(pos == tlp.pos)
	{
		distintos = false;
	}
	return distintos;
}
TListaPosicion TListaPosicion::Anterior() const
{
	TListaPosicion tlp;

	if(pos != NULL)	
	{
		if(pos->anterior != NULL)
		{
			tlp.pos = pos->anterior;
		}
	}
	return tlp;
}
TListaPosicion TListaPosicion::Siguiente() const
{
	TListaPosicion tlp;

	if(pos != NULL)	
	{
		if(pos->siguiente != NULL)
		{
			tlp.pos = pos->siguiente;
		}
	}
	return tlp;
}
		
bool TListaPosicion::EsVacia() const
{
	bool vacia = false;
	if( pos == NULL )
	{
		vacia = true;
	}
	return vacia;		
}


/***************TListaPoro********************/
//-------------------------------------------\\

TListaPoro::TListaPoro()
{
	primero = NULL;
	ultimo = NULL;
}
TListaPoro::TListaPoro(const TListaPoro& tlp)
{
	if( tlp.EsVacia() )
	{
		primero = NULL;
		ultimo = NULL;
	}else
	{
		TListaNodo *p;
	
		p = tlp.primero;
		
		primero = NULL;
		ultimo = NULL;
		
		do
		{
			Insertar(p->e);
			p = p->siguiente;
		}while( p != NULL );
		
	}
}
TListaPoro::~TListaPoro()
{
	if(primero != NULL)
	{
		TListaNodo *p, *q;

		p = primero;
		while(p != NULL)
		{
			q = p;
			p = p->siguiente;
			delete q;
		}
	}

	primero = NULL;
	ultimo = NULL;
	
}
TListaPoro& TListaPoro::operator=(const TListaPoro& tlp)
{
	primero = NULL;
	ultimo = NULL;
	
	TListaNodo *p;
	
	p = tlp.primero;
	
	primero = NULL;
	ultimo = NULL;
	
	do
	{
		Insertar(p->e);
		p = p->siguiente;
	}while( p != NULL );
	
	return (*this);
}
bool TListaPoro::operator==(const TListaPoro& tlp)
{
	bool iguales = true;
	TListaNodo *p, *q;

	q = primero;
	p = tlp.primero;
	if(Longitud() != tlp.Longitud())
	{
		iguales = false;
	}else
	{
		while(iguales==true && (p != NULL && q != NULL))
		{
			if(p->e != q->e)
			{
				iguales = false;
			}
		
			p = p->siguiente;
			q = q->siguiente;
		}
	}
	
	
	return iguales;
}
bool TListaPoro::operator!=(const TListaPoro& tlp)
{
	bool distintos = true;
	if((*this)==tlp)
	{
		distintos = false;
	}
	return distintos;		
}
TListaPoro TListaPoro::operator+(TListaPoro& tlp)
{
	
	TListaPoro l;
	l=(*this);
	
	if( tlp.EsVacia() == false )
	{
		TListaNodo *n, *r;
		TListaPosicion fin;

		
		fin = l.Ultima();
		n = tlp.primero;
		r = tlp.ultimo;
		while(n != NULL)
		{
			l.Insertar(n->e);
			fin = l.Ultima();
			n = n-> siguiente;
	
		}		
	}

	return l;
}
TListaPoro TListaPoro::operator-(TListaPoro& tlp)
{
	TListaPoro l;
	TListaNodo *n;

	l = (*this);

	if(!tlp.EsVacia())
	{
		n = tlp.primero;
		while(n != NULL)
		{
			l.Borrar(n->e);	
			n = n-> siguiente; 
		}
	}
	return l;
}
bool TListaPoro::EsVacia() const
{
	bool vacia = false;
	if(primero == NULL && ultimo == NULL)
	{
		vacia = true;
	}
	return vacia;
}
bool TListaPoro::Insertar(const TPoro& c)
{
	bool correcto = false, insertado = false;
	TListaNodo *q;
	

	if(EsVacia() )
	{
		q = new TListaNodo();
		q->e = c;
		primero = q;
		ultimo = q;
		correcto = true;
		q=NULL;			
	}else
	{
		TListaNodo *i,*j, *f;
		i = primero;
		j = i->siguiente;
		f = ultimo;
		
		if(!Buscar(c))
		{
			q = new TListaNodo();
			q->e = c;
			while( i != NULL && correcto == false && insertado == false )
			{
				if(i->e == q->e)
				{
					insertado = true;
					delete q;
				
				}else
				{
					 
					if(i->siguiente == NULL)
					{
						i->siguiente = q;
						q->anterior = i;
						ultimo = q;
						correcto = true;
						
					}else
					{
						if(i->siguiente->e.VolMayor(q->e)==true)
						{
							if(i == primero)
							{
								i->anterior = q;
								q->siguiente = i;
								primero = q;
								correcto = true;
							}else
							{
								i->siguiente = q;
								j->anterior = q;
 								q->anterior = i;
								q->siguiente = f;
								correcto = true;
							}
					
						}else
						{
							i = j;
							j = i->siguiente;
						}
					}
				}
			}
		}
		i=NULL;
		f=NULL;
		j=NULL;
	}
	q=NULL;		
	return correcto;		
}
bool TListaPoro::Borrar(const TPoro& c)
{
	bool correcto = false;
	bool pasado = false;
	TPoro aux(c);
	TListaNodo *p, *q;

	p = primero;
	q = p->siguiente;
	while( p != NULL && correcto == false && pasado == false )
	{
		if(p->e.VolMayor(aux))
		{
			pasado = true;
		}else
		{
			if( p->e == aux )
			{
				if( p == primero)
				{
					primero = q;					
					if(q)q->anterior = NULL;//q?=NULL
				}else
				{
					if( p == ultimo)
					{
						ultimo = p->anterior;
						p->anterior->siguiente = NULL;
					}else
					{
						p->anterior->siguiente = q;
						q->anterior = p->anterior;
					}
				}
				delete p;
				correcto = true;
			}
		}
		p = q;
		if(q)q = p->siguiente; //q?=NULL
	
	}
	p = NULL;
	q = NULL;

	return correcto;
}
bool TListaPoro::Borrar(const TListaPosicion& tlp)
{
	return(Borrar(tlp.pos->e));
}
TPoro TListaPoro::Obtener(const TListaPosicion& tlp) const 
{
	TPoro p;
	TListaPosicion nueva(tlp);
	if(tlp.EsVacia() == false)
	{
		p = nueva.pos->e;
	}
	return p;
}
bool TListaPoro::Buscar(const TPoro& c) const
{
	bool correcto = false;
	bool pasado = false;
	TPoro aux(c);
	TListaNodo *p;

	p = primero;
	while( p != NULL && correcto == false && pasado == false )
	{
		if(p->e.VolMayor(aux))
		{
			pasado = true;
		}else
		{
			if( p->e == aux )
			{
				correcto = true;
			}
		}
		p = p->siguiente;
	}
	return correcto;
}
int TListaPoro::Longitud() const
{
	int tamano = 0;
	TListaNodo *p;

	p = primero;
	while( p != NULL )
	{
		tamano++;
		p = p -> siguiente;
	}
	return tamano;
}
TListaPosicion TListaPoro::Primera() const
{
	TListaPosicion p;

	if( EsVacia() == false )
	{
		p.pos = primero;
	}
	return p;
}
TListaPosicion TListaPoro::Ultima() const
{
	TListaPosicion p;
	
	if( EsVacia() == false )
	{
		p.pos = ultimo;
	}
	return p;
}
ostream& operator<<(ostream &o, const TListaPoro &aux)
{
	TListaPosicion p, q;
	bool final = false;
	
	p = aux.Primera();
	q = aux.Ultima();
	int i = 0;
	o<<"(";
	while(!p.EsVacia() && final == false)
	{
		//~ cout<<i<<endl;
		if(p != q)
		{
			o<<aux.Obtener(p)<<" ";
		}else
		{
			o<<aux.Obtener(p);
		}
		
		if(!p.Siguiente().EsVacia())
		{
			p = p.Siguiente();
		}else
		{
			final = true;
		}
		i++;
	}
	o<<")";
	

	return(o);
}
